#include "library/libopt.h"
#include <apr_getopt.h>
#include <apr_strings.h>
#include <map>

using namespace std;
using namespace basic::library2;

CCommandOption::CCommandOption(apr_int32_t dwArgc, const char *Argv[], const char acceptableArgv[]) : m_dwArgc(dwArgc), m_psArgv(Argv), m_bInitOk(false), m_pstGetOpt(NULL), m_acceptableOptions(acceptableArgv)
{
    InitMemoryPool();
    if (apr_pool_create(&m_pstCmdOptPool, NULL) != APR_SUCCESS)
    {
        //throw exception
        m_LastErrorMsg = "apr_pool_create() fail";
    }
    else
    {
        if(Init() == false)
        {
            m_LastErrorMsg = "init() fail";
        }
        else
        {
            m_bInitOk = true;
        }
    }
}

CCommandOption::~CCommandOption()
{
    apr_pool_destroy(m_pstCmdOptPool);
}

//bool CCommandOption::Parse()
//{
//    if (m_bInitOk)
//        return m_bInitOk;
//    if (apr_getopt_init(&m_pstGetOpt, m_pstCmdOptPool, m_dwArgc, m_psArgv) != APR_SUCCESS)
//    {
//        //throw exception
//        return false;
//    }
//    m_bInitOk = true;
//    return true;
//}
bool CCommandOption::Init()
{
    if (apr_getopt_init(&m_pstGetOpt, m_pstCmdOptPool, m_dwArgc, m_psArgv) != APR_SUCCESS)
    {
        //throw exception
//            return false;
        m_LastErrorMsg = "apr_getopt_init() fail";
        return false;
    }
    else
    {
        apr_status_t rv;
        char cOptCh;
        const char *optarg;
        while ((rv = apr_getopt(m_pstGetOpt, m_acceptableOptions, &cOptCh, &optarg)) == APR_SUCCESS)
        {
            m_mapOptions[string(1, cOptCh)] = (optarg == NULL? string(1, '\x0'):string(optarg));
        }
        return true;
    }
}

bool CCommandOption::IsOptionExist(char cOptName)
{
    if(m_bInitOk == false)
    {
        m_LastErrorMsg = "not init properly";
        return false;
    }
    std::map<std::string, std::string>::iterator i = m_mapOptions.find(string(1, cOptName));
    if(i != m_mapOptions.end())
    {
        return true;
    }
    m_LastErrorMsg = "no option: " + string(1, cOptName);
    return false;
}

apr_status_t CCommandOption::GetValue(char cOptName, std::string &sVal)
{
//    if (Parse() == false)
//        return -1;
//
//    string sOptionName = cOptName + ":";
//    char cOptCh;
//    const char *optarg;
//    apr_status_t rv;
//
//    while ((rv = apr_getopt(m_pstGetOpt, sOptionName.c_str(), &cOptCh, &optarg)) == APR_SUCCESS)
//    {
//        if (cOptCh == cOptName)
//        {
//            sVal = optarg;
//            return APR_SUCCESS;
//        }
//    }
    if(!IsOptionExist(cOptName))
    {
        m_LastErrorMsg = "no option: " + string(1, cOptName);
        return -1;
    }
    if(m_mapOptions[string(1, cOptName)] != string(1, '\x0'))
    {
        sVal = m_mapOptions[string(1, cOptName)];
        return APR_SUCCESS;
    }
    m_LastErrorMsg = "no value for : " + string(1, cOptName);
    return -1;
}

apr_status_t CCommandOption::GetValue(char cOptName, std::string &sVal, const std::string &sDefaultVal)
{
//    if (Parse() == false)
//        return -1;
//
//    string sOptionName = cOptName + ":";
//    char cOptCh;
//    const char *optarg;
//    apr_status_t rv;
//
//    while ((rv = apr_getopt(m_pstGetOpt, sOptionName.c_str(), &cOptCh, &optarg)) == APR_SUCCESS)
//    {
//        if (cOptCh == cOptName)
//        {
//            sVal = optarg;
//            return APR_SUCCESS;
//        }
//    }
    if(IsOptionExist(cOptName) && m_mapOptions[string(1, cOptName)] != string(1, '\x0'))
    {
        sVal = m_mapOptions[string(1, cOptName)];
        return APR_SUCCESS;
    }
    sVal = sDefaultVal;
    return APR_SUCCESS;
}

apr_status_t CCommandOption::GetValue(char cOptName, apr_int32_t &dwVal)
{
//    if (Parse() == false)
//        return -1;
//    string sValue;
//    if (GetValue(cOptName, sValue) == APR_SUCCESS)
//    {
//        dwVal = (apr_int32_t) apr_atoi64(sValue.c_str());
//        return APR_SUCCESS;
//    }
    string sVal;
    if(GetValue(cOptName, sVal) != APR_SUCCESS)
        return -1;
    dwVal = (apr_int32_t) apr_atoi64(sVal.c_str());
    return APR_SUCCESS;
}

apr_status_t CCommandOption::GetValue(char cOptName, apr_int32_t &dwVal, apr_int32_t dwDefaultVal)
{
//    if (Parse() == false)
//        return -1;
//
//    if (Parse() == false)
//        return -1;
//    string sValue;
//    if (GetValue(cOptName, sValue) == APR_SUCCESS)
//    {
//        dwVal = (apr_int32_t) apr_atoi64(sValue.c_str());
//        return APR_SUCCESS;
//    }
//    dwVal = dwDefaultVal;
//    return APR_SUCCESS;
    string sVal;
    if(GetValue(cOptName, sVal) != APR_SUCCESS)
    {
        dwVal = dwDefaultVal;
        return APR_SUCCESS;
    }
    dwVal = (apr_int32_t) apr_atoi64(sVal.c_str());
    return APR_SUCCESS;
}

bool CCommandOption::HasOption(char cOptName)
{
//    if (Parse() == false)
//        return false;
//
//    string sOptionName = cOptName + "";
//    char cOptCh;
//    const char *optarg;
//    apr_status_t rv;
//
//    printf("*****************************\n");
//    while ((rv = apr_getopt(m_pstGetOpt, "ab:c"/*sOptionName.c_str()*/, &cOptCh, &optarg)) == APR_SUCCESS)
//    {
//        printf("HasOption() cOptCh: %c vs cOptName: %c\n", cOptCh, cOptName);
//        if (cOptCh == cOptName)
//        {
//            return true;
//        }
//    }
//    return false;
    return IsOptionExist(cOptName);
}

